#pragma once
#include "cem/boundary_condition.h" // 引入 BoundarySpec/BoundaryType 定义
#include "cem/material_types.h"      // 引入 AnisotropySpecEntry/LayerDepthConduction
#include "cem/material_database.h"
#include "clangd_helper.h"

#include <libmesh/equation_systems.h> // 确保 EquationSystems 完整类型可见

#include <memory>
#include <string>
#include <unordered_map>
#include <vector>

namespace libMesh
{
class LinearImplicitSystem;
class Mesh;
}

namespace cem
{

class ParameterReader; // 前向声明，避免头文件膨胀
class MeshManager;
class MaterialDatabase;
class BoundaryConditionManager;

// ElectromagneticsSystem 代表电磁学系统的高层容器。
// 负责基于给定网格创建 libMesh 方程系统、变量与边界约束，
// 并持有装配所需的材料参数映射与工作频率。
class ElectromagneticsSystem
{
public:
    // 构造函数：默认构造。
    ElectromagneticsSystem() = default;

    // 函数: initialize
    // 作用: 依据参数、网格、材料与边界条件完成系统级初始化：
    //       - 创建 EquationSystems 与 LinearImplicitSystem("EM")
    //       - 添加一个复数 HCurl 变量 "u"
    //       - 完成 es.init() 初始化
    //       - 缓存区域参数映射与角频率以供装配与求解
    void initialize(const ParameterReader & params,
                    const MeshManager & mesh,
                    const MaterialDatabase & materials,
                    const BoundaryConditionManager & bcs);

    // 函数: name
    // 作用: 返回系统名称（供日志或调试）。
    // 参数: 无
    // 返回: 字符串
    std::string name() const;

    // 函数: equation_systems
    // 作用: 访问内部 EquationSystems（只读/可写）。
    libMesh::EquationSystems & equation_systems();
    const libMesh::EquationSystems & equation_systems() const;

    // 函数: linear_system
    // 作用: 访问内部线性隐式方程系统（EM）。
    libMesh::LinearImplicitSystem & linear_system();
    const libMesh::LinearImplicitSystem & linear_system() const;

    // 函数: variable_name
    // 作用: 返回默认主变量名称（当前为 "u"）。
    const std::string & variable_name() const { return _variable_name; }

    // 函数: variable index
    // 作用: 获取复数变量索引。
    unsigned int var_index() const { return _var; }

    // 函数: material_manager
    // 作用: 提供集中式材料管理器访问接口（可写/只读）。
    //      装配器与后处理模块应通过该管理器统一获取材料张量，避免散落查询。
    MaterialDatabase & material_manager() { return _material_manager; }
    const MaterialDatabase & material_manager() const { return _material_manager; }

    // 函数: omega
    // 作用: 获取当前角频率（rad/s）。
    double omega() const { return _omega; }

    // 函数: set_omega
    // 作用: 覆盖当前角频率（rad/s）。
    // 参数: omega - 角频率(rad/s)
    // 说明: 当需要在并行子通信器内为不同频率分别求解时，可在 initialize 之后调用该方法。
    void set_omega(double omega) { _omega = omega; }

    // 函数: boundary_specs
    // 作用: 返回边界条件规格列表（在 initialize 中从管理器拷贝）。
    // 参数: 无
    // 返回: 边界规格常量引用
    const std::vector<BoundarySpec> & boundary_specs() const { return _boundary_specs; }

    const std::vector<LayerDepthConduction> & layers() const { return _layers; }

private:
    std::unique_ptr<libMesh::EquationSystems> _equation_systems; // 方程系统容器
    std::string _system_name{"EM"};
    std::string _variable_name{"u"};

    // 变量索引（单复变量）
    unsigned int _var{0};

    // 集中式材料管理器（组合）：负责缓存并统一提供材料张量
    MaterialDatabase _material_manager;

    // 角频率（rad/s），若未指定频率则为 0.0
    double _omega{0.0};

    // 边界条件规格（用于装配边界项）
    std::vector<BoundarySpec> _boundary_specs;

    std::vector<LayerDepthConduction> _layers;
};

} // namespace cem